#include "constants.h";

XfMissionChapterExecute={
	private ["_chapter_succeeded"];
	diag_log "";
	diag_log "=========================================================================";
	diag_log "                             CHAPTER 1                                   ";
	diag_log "=========================================================================";
	diag_log "";
	diag_log Format["(%1)[%2]: %3; %4",diag_tickTime,"chapter1.sqf","XfMissionChapterExecute","Starting Chapter","_last_random_reinforcement","_random_reinf_diff","_reinforcement_power"];
	DM_Mission_ArtilleryVariables = [];
	DM_Mission_Chapter_CanRun = True;
	DM_Mission_Chapter_Runs = True;
	DM_Mission_Chapter_Success = 0;
	call XfMissionChapterSetup;
	_chapter_succeeded = false;
	if (!DM_Mission_Mission_CanRun) exitWith {diag_log Format["(%1)[%2]: %3; %4",diag_tickTime,"chapter1.sqf","XfMissionChapterSetup","Mission canceled!"];};
	
	private ["_contact","_contacts","_towns","_ceo","_task_name","_tasks"];
	_random_town = DM_Chapter_Location;
	_random_town_pos = _random_town select XF_MAP_LOCATION_CENTER;
	_random_town_pos_size = _random_town select XF_MAP_LOCATION_SIZE;
	_ceo = DM_VIP;
	_ceo_start_pos = getPos _ceo;
	_towns = DM_Chapter_Data select 0;
	_contacts = DM_Chapter_Data select 1;
	_vip_arrived = false;
	_vip_alive = true;
	_tasks = [];
	_make_talk = {
		private ["_character","_time_out","_move","_moves"];
		_character = _this select 0;
		_time_out = _this select 1;
		_moves = [
			"AidlPercSnonWnonDnon_talk1"
		];	
		while {_time_out > time && alive _character} do {
			_move = _moves call XfRandomArrayVal;
			_character playMove _move;
			sleep 5;
		};
	};
		
	_fnc_KeepInPlace = {
		_unit = _this select 0;
		_unit setUnitPos "Middle";
		_initial_pos = getPos _unit;
		doStop _unit;
		while { alive _unit && ((behaviour _unit) in ["CARELESS","SAFE"]) && ((combatMode (group _unit)) != "RED") } do {
			if ((_unit distance _initial_pos) > 2) then { _unit doMove _initial_pos; };
			sleep 1.23456;
		};
		if (d_mission_debug_messages) then { diag_log Format["(%1)[%2]: %3: %4 : %5",diag_tickTime,"chapter1.sqf","XfMissionChapterExecute","KeepInPlace",[_unit, (behaviour _unit)]];};
	};
	
	_vip_leading = false;
	_at_destination_time_out = 0;
	_current_contact = 0;
	_road_group_created = false;
	_town_group_created = false;
	_town_group = grpNull;
	_road_group = grpNull;
	_vip_last_pos = [];

	_contact = _contacts select _current_contact;
	_contact_pos = getPos _contact;
	// We filter the list of possible buildings to those who contain inside hiding positions.
	_building_list = [1,-1,1] call XfBuildingFilteredList;
	
	diag_log Format["(%1)[%2]: %3: %4: %5, %6",diag_tickTime,"chapter1.sqf","XfMissionChapterExecute","Entering the loop",[_ceo], Time];
	while {DM_Mission_Chapter_CanRun AND DM_Mission_Mission_CanRun} do {
		sleep 10;
		_vip_arrived = ["jip_lead_vip",false] call XNetGetJIP;
		_vip_alive = alive _ceo;

		// Creating or handling Ambush group inside town
		if (!_town_group_created) then {
			if (d_mission_debug_messages) then {
				diag_log Format["(%1)[%2]: %3: %4 : %5",diag_tickTime,"chapter1.sqf","XfMissionChapterExecute","CreateTownGroup",_current_contact];
			};
			_players = call XPlayersNumber;
			// We determine the max amount of enemies per group depending on the number of players
			_amount = 3;
			_groups = 1;
			switch (true) do {
				case (_players <= 5): { _amount = 4; _groups = 2;};
				case (_players <= 10): { _amount = 6; _groups = 2;};
				case (_players <= 15): { _amount = 50; _groups = 2;};
				case (_players <= 20): { _amount = 50; _groups = 3;};
				default {_amount = 50; _groups = 4;};
			};	

			// 1) We calculate the possible hiding positions around the contact
			_buildings = nearestObjects [_contact_pos, _building_list, 150];
			_building_pos_hiding = [];
			for [{_i = 0},{_i < (count _buildings)},{_i = _i + 1}] do {
				_building = _buildings select _i;
				// We don't place enemies less than 50m away from the contact
				if (_building distance _contact_pos < 50) then {
					_buildings set [_i, "xXdelXx"];
				} else {
					// We only take into account hiding positions (so we don't end up on roofs/doors)
					_building_pos_hiding = [_building_pos_hiding, ([_building,"HIDE", false] call XfBuildingPosArrayASL)] call XfArrayPushStack;
				};
			};
			_buildings = _buildings - ["xXdelXx"];
			if (d_mission_debug_messages) then {
				diag_log Format["(%1)[%2]: %3: %4 : %5",diag_tickTime,"chapter1.sqf","XfMissionChapterExecute","Buildings_Town_Group",_buildings];
				diag_log Format["(%1)[%2]: %3: %4 : %5",diag_tickTime,"chapter1.sqf","XfMissionChapterExecute","Buildings_Pos_Hiding",_building_pos_hiding];
			};
			// We check if we found positions to hide or not
			if (count _building_pos_hiding <= 0) then {
				// In case we didn't find any good hiding positions inside buildings. What we'll do is just pick random positions up.
				for [{_i = 0},{_i < 10},{_i = _i + 1}] do {
					_random_pos = [_contact_pos, 200, 100] call XfGetRanPointCircle;
					if (count _random_pos > 0) then {
						_building_pos_hiding set [ count _building_pos_hiding, _random_pos];
					};
				};
				if (d_mission_debug_messages) then {
					diag_log Format["(%1)[%2]: %3: %4 : %5",diag_tickTime,"chapter1.sqf","XfMissionChapterExecute","Buildings_Pos_Hiding",_building_pos_hiding];
				};
			};
			
			// Now we create enemy soldiers at the respawn point for enemies.
			_town_group_created = true;
			// We create a random group with Task Defend, so they don't move initially.
			_town_group = [d_enemy_side] call x_creategroup;
			
			_town_group setBehaviour "CARELESS";
			_town_group setCombatMode "YELLOW";
			for [{_i = 0}, {_i < count (waypoints _town_group)}, {_i = _i+ 1}] do {
				deleteWaypoint [_town_group, _i];
			};
			_wp = _town_group addWaypoint [_contact_pos, 0];
			_wp setWaypointBehaviour "CARELESS";
			_wp setWaypointSpeed "FULL";
			_wp setwaypointtype "MOVE";
			_wp setWaypointFormation "VEE";
			_town_group setCurrentWayPoint _wp;
			
			for [{_i = 0}, {_i < _groups}, {_i = _i+ 1}] do {
				[_town_group,(getMarkerPos "respawn_east"),[],floor(random(5)), false] call XfMissionCreateFootmenGroup;
			};
			if (d_mission_debug_messages) then { diag_log Format["(%1)[%2]: %3: %4 : %5",diag_tickTime,"chapter1.sqf","XfMissionChapterExecute","Group Content",(units _town_group)]; };
			if (count (units _town_group) > (_groups * _amount)) then {
				// We remove excess units
				for [{_i = (_groups * _amount)}, {_i < count (units _town_group)}, {_i = _i+ 1}] do {
					deleteVehicle ((units _town_group) select _i);
				};
				if (d_mission_debug_messages) then { diag_log Format["(%1)[%2]: %3: %4 : %5",diag_tickTime,"chapter1.sqf","XfMissionChapterExecute","Removed Units",(units _town_group)]; };
			};
			// Next we place those soldiers inside the hiding positions.
			{
				_x setBehaviour "CARELESS";
				_x setPosAsl (_building_pos_hiding call XfRandomArrayVal);
				doStop _x;
				[_x] spawn _fnc_KeepInPlace;
				if (d_mission_debug_messages) then { [false,[format["chapter1_town_%1_%2",_current_contact,_i], (getPos _x), "ICON", "ColorRed", [0.7,0.7],"",0,"mil_triangle","",0.7]] call XfMissionMarker; };
				_i = _i + 1;
			} foreach (units _town_group);
		} else {
			if ((((vehicle _ceo) distance _contact_pos) < 50) && ((count (units _town_group)) > 0)) then {
				_town_group setBehaviour "STEALTH";
				_town_group setCombatMode "RED";
				{
					_x setBehaviour "STEALTH";
					_x doMove (getPos (vehicle _ceo));
				} foreach (units _town_group);
			};
		};
		
		// Creating or handling ambush group on road
		if (!_road_group_created) then {
			if ((_ceo distance _contact_pos) > 700) then {
				if (d_mission_debug_messages) then {
					diag_log Format["(%1)[%2]: %3: %4 : %5",diag_tickTime,"chapter1.sqf","XfMissionChapterExecute","CreateRoadGroup",_current_contact];
				};
				_road_group_created = true;

				_players = call XPlayersNumber;
				// We determine the max amount of enemies per group depending on the number of players
				_amount = 3;
				_groups = 1;
				switch (true) do {
					case (_players <= 5): { _amount = 6; _groups = 1;};
					case (_players <= 10): { _amount = 10; _groups = 1;};
					case (_players <= 15): { _amount = 50; _groups = 1;};
					case (_players <= 20): { _amount = 50; _groups = 1;};
					default {_amount = 50; _groups = 1;};
				};	
				
				// We need to find a road on the way between the current position of the CEO and the next contact
				
				_ambush_point = [];
				_start_calculation = time;
				_path = [_contact_pos, (getPos _ceo), 500] call XfGetRoadPath;
				if (d_mission_debug_messages) then { diag_log Format["(%1)[%2]: %3: %4 : %5",diag_tickTime,"chapter1.sqf","XfMissionChapterExecute","Path Calculated",[(time - _start_calculation),(count _path)]]; };
				if (count _path > 0) then {
					_path_points = count _path;
					_path_pos = ceil (_path_points / 2);
					_ambush_point = _path select _path_pos;
					if (d_mission_debug_messages) then { diag_log Format["(%1)[%2]: %3: %4 : %5",diag_tickTime,"chapter1.sqf","XfMissionChapterExecute","Ambush",[(_ambush_point distance (vehicle _ceo))]]; };
					if ((_ambush_point distance (vehicle _ceo)) > 600) then {
						if (count _ambush_point > 0) then {
							if (d_mission_debug_messages) then { [false,[format["chapter1_road_%1",_current_contact], _ambush_point, "ICON", "ColorRed", [0.7,0.7],"",0,"mil_triangle","",0.7]] call XfMissionMarker; };
							_road_group_created = true;
							_ambush_zone = format["chapter1_ambush_%1",_current_contact];
							[(!d_mission_debug_messages),[_ambush_zone, _ambush_point, "ELLIPSE", "ColorRed", [60,60],"",0,"","",0.7]] call XfMissionMarker;
							for [{_i = 0}, {_i < _groups}, {_i = _i+ 1}] do {
								_road_group = [d_enemy_side,_ambush_point,[_ambush_zone,"noveh","ambush"],floor(random(5)), false] call XfMissionCreateFootmenGroup;
								if (d_mission_debug_messages) then { diag_log Format["(%1)[%2]: %3: %4 : %5",diag_tickTime,"chapter1.sqf","XfMissionChapterExecute","Group Content",(units _road_group)]; };
								if (count (units _road_group) > (_amount)) then {
									// We remove excess units
									for [{_i = (_amount)}, {_i < count (units _road_group)}, {_i = _i+ 1}] do {
										deleteVehicle ((units _road_group) select _i);
									};
									if (d_mission_debug_messages) then { diag_log Format["(%1)[%2]: %3: %4 : %5",diag_tickTime,"chapter1.sqf","XfMissionChapterExecute","Removed Units",(units _road_group)]; };
								};
							};
						};
					};
				};
			};
		};
		if (_vip_alive) then {
			// We check whether the CEO is at destination or not.
			if (!_vip_arrived) then {
				// We check that the CEO is now being lead by someone while it WAS NOT the case a moment ago
				if ((leader (group _ceo) != _ceo) && !_vip_leading) then {
					// in such a case, we can erase the marker
					_vip_leading = true;
				} else {
					// We check that the CEO is not being lead by anyone while it WAS the case a moment ago
					if ((leader (group _ceo) == _ceo) && _vip_leading) then {
						// In such a case, we set the marker again.
						_vip_leading = false;
						doStop _ceo;
						[false,["chapter1_ceo_position", (getPos _ceo), "ICON", "ColorRed", [0.7,0.7],"V.I.P.",0,"hd_flag","",0.7]] call XfMissionMarker;
					} else {
						// Do nothing, we're driving/walking/flying/riding
					};
				};
			} else {
				// We check if we are waiting for the conversation to finish or if it hasn't started yet
				if (_at_destination_time_out <= 0) then {
					// It hasn't started yet.
					_task_name = Format["LeadVIP%1", _current_contact];
					if (_tasks find _task_name < 0) then {
						_tasks set [count _tasks, _task_name];
						[_task_name,"", "","",[],"Succeeded"] call XfMissionTask;
						[false,[Format["chapter1_contact_position_%1", _current_contact]]] call XfMissionMarker;
						[false,["chapter1_ceo_position"]] call XfMissionMarker;
						_contact = _contacts select _current_contact;
						_contact_dir = getDir _contact;
						_contact_pos_x = ((getPos _contact) select 0) + 1.5 * (sin _contact_dir);
						_contact_pos_y = ((getPos _contact) select 1) + 1.5 * (cos _contact_dir);
						_ceo_position = [_contact_pos_x,_contact_pos_y,0];
						_end_move = time + 10;
						_ceo enableAI "MOVE";
						while {((_ceo distance _ceo_position) > 0.1) && _end_move > time && alive _ceo} do {
							_ceo doMove _ceo_position;
							sleep 0.423;
						};
						_at_destination_time_out = time + 30;
						if (alive _ceo) then {
							if ((_ceo distance _ceo_position) > 0.3) then { _ceo setPos _ceo_position; };
							_contact_dir = [_ceo, _contact] call XfDirTo;;
							_ceo setDir (_contact_dir);
							_contact setDir (_contact_dir + 180);
							_ceo disableAI "MOVE";
							sleep 5;
							[_ceo, _at_destination_time_out] spawn _make_talk;
							[_contact, _at_destination_time_out] spawn _make_talk;
						};
					};
					// Closing current task
				} else {
					if (_at_destination_time_out > 0 && _at_destination_time_out < time) then {
						_at_destination_time_out = 0;
						// Picking up next task
						_current_contact = _current_contact + 1;
						_ceo enableAI "MOVE";
						if (_current_contact >= (count _contacts)) then {
							// Return to start position
							_contact_pos = _ceo_start_pos;
							[_ceo,(group _ceo),(getPos _ceo),"LEAD",["STR_MF_M_CLOSE_AT_START","STR_MF_YOUDIDYOURBEST","jip_lead_vip","jip_vip_alive",[_ceo_start_pos,[50,50],0,false]],""] call XfMissionCreateMissionUnit;
							[false,[Format["chapter1_contact_position_%1", _current_contact], _ceo_start_pos, "ICON", "ColorRed", [0.7,0.7],"Contact",0,"hd_end","",0.7]] call XfMissionMarker;
							[Format["LeadVIP%1", _current_contact],"STR_MF_M_CLOSE_TASK_BACK", "STR_MF_M_CLOSE_TASK_BACK_DESC","",[],"Created"] call XfMissionTask;
							_town_group_created = true;
							_town_group = grpNull;
						} else {
							// Go to next contact
							_contact_town_name = (_towns select _current_contact) select XF_MAP_LOCATION_DISPLAYNAME;
							_contact = _contacts select _current_contact;
							_contact_pos = getPos _contact;
							[_ceo,(group _ceo),(getPos _ceo),"REGISTER",[],""] call XfMissionCreateMissionUnit;
							[_ceo,(group _ceo),(getPos _ceo),"LEAD",["STR_MF_M_CLOSE_AT_CONTACT","STR_MF_YOUDIDYOURBEST","jip_lead_vip","jip_vip_alive",[_contact_pos,[10,10],0,false],"if (isServer) then {_grp = [d_own_side] call x_creategroup; [DM_VIP] joinSilent _grp; [0, _grp, 'CEO', 'MissionFramework'] call ACV_FNCT_PutInStock;};"],""] call XfMissionCreateMissionUnit;
							[false,[Format["chapter1_contact_position_%1", _current_contact], _contact_pos, "ICON", "ColorRed", [0.7,0.7],"",0,"hd_end","",0.7]] call XfMissionMarker;
							[Format["LeadVIP%1", _current_contact],"STR_MF_M_CLOSE_TASK_LEAD", ["STR_MF_M_CLOSE_TASK_LEAD_DESC",_contact_town_name],"",[],"Created"] call XfMissionTask;
							// We only create town groups if the next contact is a person
							_town_group_created = false;
							_town_group = grpNull;
						};
						[false,["chapter1_ceo_position", (getPos _ceo), "ICON", "ColorRed", [0.7,0.7],"V.I.P.",0,"hd_flag","",0.7]] call XfMissionMarker;
						["jip_lead_vip",false] call XNetSetJIP;
						_vip_arrived = false;
						_road_group_created = false;
						_road_group = grpNull;
					};
				};
			};
		};
		if (!_vip_alive) then {
			DM_Mission_Chapter_CanRun = false;
			_chapter_succeeded = false;
		} else {
			_vip_last_pos = getPos _ceo;
			if (_current_contact >= (count _contacts) && _vip_arrived) then {
				[Format["LeadVIP%1", _current_contact],"", "","",[],"Succeeded"] call XfMissionTask;
				DM_Mission_Chapter_CanRun = false;
				_chapter_succeeded = true;
			};
		};
	};
	sleep 15;
	if (DM_Mission_Mission_CanRun) then {
		if (_chapter_succeeded) then {
			call XfMissionChapterSuccess;
		} else {
			call XfMissionChapterFailure;
		};
	} else {
		diag_log Format["(%1)[%2]: %3; %4",diag_tickTime,"chapter1.sqf","XfMissionChapterExecute","Mission canceled!"];
	};
	sleep 30;
	While {DM_Mission_Mission_CanRun && _enemy_count > 1 && _players_found} do {
		sleep 5;
		if (X_MP) then {
			_players_found = false;
			{
				if (([(getPos _x), _vip_last_pos, 250] call XfPointInCircle) && isplayer _x) exitWith { _players_found = true; };
			} foreach playableUnits;
		} else {
			_players_found = ([(getPos player), _vip_last_pos, 250] call XfPointInCircle);
		};
		_enemy_count = (([_vip_last_pos,(250),d_enemy_side] call XfMissionGetZoneSideCount) select 0);
		if (d_mission_debug_messages) then { diag_log Format["(%1)[%2]: %3: %4: player:%5  enemies:%6",diag_tickTime,"chapter1.sqf","XfMissionChapterExecute","Chapter End Check",_players_found,_enemy_count]; };
	};

	// Just in case a reinforcement is already on the way.
	call XfMissionCancelReinforcement;
	call XfMissionChapterCleanUp;
	DM_Mission_Chapter_Runs = False;
};

XfMissionChapterSetup={
	private ["_random_town","_random_town_pos","_random_town_pos_size","_troops_power","_troops_coeff","_grpSpecOps","_i","_grp","_ceo_type","_ceo_position"
			,"_contact","_contacts","_visiting_towns","_grp_civ","_contact_pos","_loc_pos","_loc_size"];
	diag_log Format["(%1)[%2]: %3; %4 %5",diag_tickTime,"chapter1.sqf","XfMissionChapterSetup","Starting Initialization:",DM_Mission_Name];
	
	_random_town = [];
	_random_town_pos = [];
	_random_town_pos_size = 150;
	_i_tries = 20;
	_towns_to_visit = 3;
	_town_radius = 5000;
	_world_center = getArray (configFile>>"CfgWorlds">>worldName >> "centerPosition");
	_world_max_size = (_world_center select 0) max (_world_center select 1);
	_town_radius = _world_max_size / 2;
	_visiting_towns = [];
	if (d_mission_debug_messages) then { diag_log Format["(%1)[%2]: %3: %4 : %5",diag_tickTime,"chapter1.sqf","XfMissionChapterSetup","Picking Town",[_world_center, _town_radius]];};
	while { ((count _random_town) <= 0) && (_i_tries > 0) && DM_Mission_Mission_CanRun && DM_Mission_Chapter_CanRun } do {
		_random_town = [True] call XfMissionGetRandomTown;
		_visiting_towns = [];
		if ( count _random_town > 0 ) then {
			_random_town_pos = _random_town select XF_MAP_LOCATION_CENTER;
			_random_town_pos_size = _random_town select XF_MAP_LOCATION_SIZE;
			
			_visiting_towns = [_random_town_pos,_town_radius,True] call XfMissionGetTownsInRange;
			if (count _visiting_towns <= _towns_to_visit) then {
				_random_town = [];
			} else {
				// If there are enough candidate towns, we filter out those which don't have houses near roads
				for [{_i = 0},{_i < (count _visiting_towns)},{_i = _i + 1}] do {
					_loc_pos = (_visiting_towns select _i) select XF_MAP_LOCATION_CENTER;
					_loc_size = (_visiting_towns select _i) select XF_MAP_LOCATION_SIZE;
					_roads = _loc_pos nearRoads _loc_size;				
					_found = false;
					{
						_house = (getPos _x) nearestObject "House";
						if ((_house distance _x) < 15) exitWith {
							_found = true;
						};
					} foreach _roads;
					if (!_found) then { _visiting_towns set [_i, "XxDeLxX"]; };
				};
				_visiting_towns = _visiting_towns - ["XxDeLxX"];
				// Next we filter out towns which are too close to other towns
				_done = false;
				_current_town = 0;
				while { _current_town < (count _visiting_towns) } do {
					_town_center = (_visiting_towns select _current_town) select XF_MAP_LOCATION_CENTER;
					for [{_i = 0},{_i < (count _visiting_towns)},{_i = _i + 1}] do {
						if (_i != _current_town) then {
							_loc_pos = (_visiting_towns select _i) select XF_MAP_LOCATION_CENTER;
							if ((_loc_pos distance _town_center) < 500) then { _visiting_towns set [_i, "XxDeLxX"]; };
						};
					};
					_visiting_towns = _visiting_towns - ["XxDeLxX"];
					_current_town = _current_town + 1;
				};
				
				// We control again after filtering if we found enough houses.
				if (count _visiting_towns <= _towns_to_visit) then {
					_random_town = [];
				} else {
					_idx = _visiting_towns call XfRandomFloorArray;
					_random_town = _visiting_towns select _idx;
					_visiting_towns set [_idx, "XxDeLxX"];
					_visiting_towns = _visiting_towns - ["XxDeLxX"];
					if (count _visiting_towns > _towns_to_visit) then {
						for [{_i = _towns_to_visit},{_i < (count _visiting_towns)},{_i = _i + 1}] do {
							_visiting_towns set [_i, "XxDeLxX"];
						};
					};
					_visiting_towns = _visiting_towns - ["XxDeLxX"];
				};
			};
		};
		_i_tries = _i_tries - 1;
	};
	if ((count _random_town) <= 0) exitWith {"STR_MF_RANDOMTOWNFAILED" call XfMissionMessageToAll; DM_Mission_Mission_CanRun = false; DM_Mission_Chapter_CanRun = false;};
	_random_town_pos_name = _random_town select XF_MAP_LOCATION_DISPLAYNAME;
	diag_log Format["(%1)[%2]: %3: %4: %5",diag_tickTime,"chapter1.sqf","XfMissionChapterSetup","Picked up", _random_town];
	diag_log Format["(%1)[%2]: %3: %4: %5",diag_tickTime,"chapter1.sqf","XfMissionChapterSetup","Visiting", _visiting_towns];
	
	DM_Chapter_Location = _random_town;
	DM_Chapter_Position = _random_town_pos;
	
	_random_town_pos = _random_town select XF_MAP_LOCATION_CENTER;
	_random_town_pos_size = _random_town select XF_MAP_LOCATION_SIZE;
	
	DM_Mission_Civilians = 1;
	_players = call XPlayersNumber;
	_kamikaze = DM_Mission_KamikazeUnit;
	DM_Mission_KamikazeUnit = false;
	_amount = 15 + _random_town_pos_size / 40;
	[[_random_town_pos,_random_town_pos_size * 0.8],"CIV",_amount] call XfMissionCivilianSpawn;
	_ceo_type = ([d_own_side,[XF_MISSION_CHAR_CIVILIAN_WOMEN]] call XfMissionGetCharacter);
	_ceo_position = [];
	_roads = _random_town_pos nearRoads _random_town_pos_size;
	_roads = _roads call XfRandomArray;
	{
		_house = (getPos _x) nearestObject "House";
		if ((_house distance _x) < 15) exitWith {
			_contact_dir = [_house, _x] call XfDirTo;
			_contact_pos_x = ((getPos _x) select 0) + 4 * (sin _contact_dir);
			_contact_pos_y = ((getPos _x) select 1) + 4 * (cos _contact_dir);
			_ceo_position = [[_contact_pos_x,_contact_pos_y,0.2], (_contact_dir + 180)];
		};
	} foreach _roads;
	while {(count _ceo_position < 0)} do {
		_ceo_position = [_random_town_pos, (_random_town_pos_size * 0.5)] call XfGetRanPointCircleBig;
	};
	_grp_civ = [civilian] call x_creategroup;
	_contacts = [];
	{
		_loc_pos = _x select XF_MAP_LOCATION_CENTER;
		_loc_size = _x select XF_MAP_LOCATION_SIZE;
		_amount = 15 + _loc_size / 40;
		[[_loc_pos,_loc_size * 0.8],"CIV",_amount] call XfMissionCivilianSpawn;
		// Get Contact Position and direction: find  a road, find closest building, find spot in front on the road. Get position and direction.
		_roads = _loc_pos nearRoads _loc_size;
		_roads = _roads call XfRandomArray;
		_road = objNull;
		_house = objNull;
		{
			_house = (getPos _x) nearestObject "House";
			if ((_house distance _x) < 15) exitWith {
				_road = _x;
			};
		} foreach _roads;
		_contact_pos = [];
		if (!isnull _road) then {
			_contact_dir = [_road, _house] call XfDirTo;
			_contact_pos_x = ((getPos _road) select 0) + 4.6 * (sin _contact_dir);
			_contact_pos_y = ((getPos _road) select 1) + 4.6 * (cos _contact_dir);
			_contact_pos = [_contact_pos_x,_contact_pos_y,0.2];
		} else {
			_contact_pos = [_loc_pos, (_loc_size * 0.5)] call XfGetRanPointCircleBig;
		};
		if (count _contact_pos <= 0) then {
			_contact_pos = [_loc_pos, (_loc_size * 0.5)] call XfGetRanPointCircle;
		};
		_contact = (["GUER",[XF_MISSION_CHAR_CIVILIAN_MEN]] call XfMissionGetCharacter);
		_contact = [_contact,_grp_civ,[_contact_pos,(_contact_dir + 180)],"REGISTER",[],"doStop this;"] call XfMissionCreateMissionUnit;
		_contact disableAI "MOVE";
		_contact allowDamage false;
		_contact setCaptive true;
		_contact setPos _contact_pos;
		_contact setDir (_contact_dir + 180);
		_contacts set [count _contacts, _contact];
		if (d_mission_debug_messages) then { diag_log Format["(%1)[%2]: %3: %4: %5",diag_tickTime,"chapter1.sqf","XfMissionChapterSetup","Contact", [_loc_pos, _loc_size, _contact_pos, typeof _contact, _contact, count _roads]]; };
		if (d_mission_debug_messages) then { [false,[format["chapter1_contact_%1_%2",_contact_pos_x,_contact_pos_y], _contact_pos, "ICON", "ColorBlue", [0.7,0.7],"",0,"hd_flag","",0.7]] call XfMissionMarker; };
	} foreach _visiting_towns;
	if (d_mission_debug_messages) then { diag_log Format["(%1)[%2]: %3: %4: %5",diag_tickTime,"chapter1.sqf","XfMissionChapterSetup","Contacts", _contacts]; };
	
	_first_town = (_visiting_towns select 0);
	_contact_town_pos = getPos (_contacts select 0);
	["jip_lead_vip",false] call XNetSetJIP;
	["jip_vip_alive",true] call XNetSetJIP;
	_grp = [d_own_side] call x_creategroup;
	diag_log Format["(%1)[%2]: %3: %4: %5",diag_tickTime,"chapter1.sqf","XfMissionChapterSetup","VIP", [_ceo_type,_grp,_ceo_position]];
	DM_VIP = [_ceo_type,_grp,_ceo_position,"LEAD",["STR_MF_M_CLOSE_AT_CONTACT","STR_MF_YOUDIDYOURBEST","jip_lead_vip","jip_vip_alive",[_contact_town_pos,[10,10],0,false],"if (isServer) then {_grp = [d_own_side] call x_creategroup; [DM_VIP] joinSilent _grp; [0, _grp, 'CEO', 'MissionFramework'] call ACV_FNCT_PutInStock;};"],"doStop this; removeAllWeapons this;"] call XfMissionCreateMissionUnit;
	DM_VIP setPos (_ceo_position select 0);
	DM_VIP setDir (_ceo_position select 1);
	
	_contact_town_name = _first_town select XF_MAP_LOCATION_DISPLAYNAME;
	["LeadVIP0","STR_MF_M_CLOSE_TASK_LEAD", ["STR_MF_M_CLOSE_TASK_LEAD_DESC",_contact_town_name],"",[],"Created"] call XfMissionTask;
	DM_Mission_KamikazeUnit = _kamikaze;

	DM_Chapter_Data = [_visiting_towns,_contacts];
		
	// This indicates where the mission takes place
	[_random_town_pos,_random_town_pos_size,_random_town_pos_name] call XfMissionCurrentPosition;
	_teleporter = [_random_town_pos] call XfMissionRandomStartTeleporter;
	// If no spot found, we get back an empty position.
	if (count (_teleporter select 0) > 0) then {
		[false,["chapter1_start_position",(_teleporter select 0), "ICON", "ColorBlue", [1,1],"",(_teleporter select 1),"hd_start","",1]] call XfMissionMarker;
	};

	[false,["chapter1_ceo_position", (_ceo_position select 0), "ICON", "ColorRed", [0.7,0.7],"V.I.P.",0,"hd_flag","",0.7]] call XfMissionMarker;
	[false,["chapter1_contact_position_0", _contact_town_pos, "ICON", "ColorRed", [0.7,0.7],"Contact",0,"hd_end","",0.7]] call XfMissionMarker;
};

XfMissionChapterSuccess={
	diag_log Format["(%1)[%2]: %3; %4",diag_tickTime,"chapter1.sqf","XfMissionChapterSuccess","Starting"];
	"STR_MF_M_CLOSE_SUCCESS" call XfMissionMessageToAll;
	DM_Mission_Chapter_Success = 1;
};

XfMissionChapterFailure={
	diag_log Format["(%1)[%2]: %3; %4",diag_tickTime,"chapter1.sqf","XfMissionChapterFailure","Starting"];
	"STR_MF_M_CLOSE_FAILURE" call XfMissionMessageToAll;
	DM_Mission_Chapter_Success = -1;
};

// Self-explanatory
XfMissionChapterCleanUp={
	diag_log Format["(%1)[%2]: %3; %4",diag_tickTime,"chapter1.sqf","XfMissionChapterCleanUp","Starting"];
	// Giving an empty position places the teleporter back to the hangar, closing the hangar.
	[[],0] call XfMissionPlaceStartTeleporter;
	[] call XfMissionCleanMarkers;
	[] call XfMissionCleanTriggers;
	[] call XfMissionCleanTasks;
};

DM_Mission_Chapter_Compiled = true;